﻿using System;
using System.Linq;
using Microsoft.Win32;
using System.IO;

namespace InstallWSPBuilderForms
{


    internal static class InstallationEngine
    {
        /// <summary>
        /// This method returns number of bits the OS uses to store an Int Pointer
        /// </summary>
        /// <returns></returns>
        /// <remarks>This value depends on "bitness" of the application, 
        /// so assembly containing this method should always be compiled as CPU agnostic (Any CPU), 
        /// so that .NET Runtime can set the right architecture (32-bit/64-bit) for it. This was tested.
        /// </remarks>
        internal static int GetSystemBitCount()
        {
            const int bitsInByte = 8;
            IntPtr s = new IntPtr();
            return System.Runtime.InteropServices.Marshal.SizeOf(s) * bitsInByte;
        }

        internal static Bitness GetSystemBitness()
        {
            return (Bitness)GetSystemBitCount();
        }

       


        internal static InstallationResult PerformInstall(Bitness osBitness, VisualStudioVersion vsVersionEnum, Bitness vsBitness)
        {
            const string PROJECT_TEMPLATE_NAME = "MOSS Solution Builder Project.zip";

            string vsInstallPath = ReadVsInstallPath(osBitness, vsVersionEnum, vsBitness);
            if (string.IsNullOrEmpty(vsInstallPath))
            {
                return new InstallationResult(false, "Could not find Visual Studio install path.\nBe sure to correctly set configuration options before installation.\n\nInstallatian failed and nothing was written to disk.");
            }
            DirectoryInfo IDE = new DirectoryInfo(vsInstallPath);

            string projectTemplatesPath = IDE.FullName + "ProjectTemplates";
            DirectoryInfo projectTemplates = new DirectoryInfo(projectTemplatesPath);
            string mossFinnaticsPath = projectTemplatesPath + @"\SharePoint_RF";

            DirectoryInfo mossFinnatics = new DirectoryInfo(mossFinnaticsPath);
            if (!mossFinnatics.Exists)
            {
                    mossFinnatics = projectTemplates.CreateSubdirectory("SharePoint_RF");
            }

            if (CopyTemplate(PROJECT_TEMPLATE_NAME, mossFinnatics) == false)
            {
                return new InstallationResult(false, "Could not copy project template to destination folder.\nInstalation failed, but probably no files were overwritten.");
            }

            // execute Visual Studio with the installvstemplates swtich to reset the templates available in the new project dialog
            if (InstallTemplatesWithVisualStudio(IDE) == false)
            {
                return new InstallationResult(false, "Could not copy project template to destination folder.\nInstalation failed, but some files were overwritten.");
            }

            return new InstallationResult(true, "Instalation complete, successfully.");
        }

        private static string ReadVsInstallPath(Bitness osBitness, VisualStudioVersion vsVersionEnum, Bitness vsBitness)
        {
            string vsRegInstallPath = @"SOFTWARE\";

            if (osBitness == Bitness.x64 && vsBitness == Bitness.x32)
            {
                vsRegInstallPath += @"Wow6432Node\";
            }
            vsRegInstallPath += @"Microsoft\VisualStudio\" + vsVersionEnum.InternalVersionString();

            RegistryKey vsInstallkey = Registry.LocalMachine.OpenSubKey(vsRegInstallPath);

            return vsInstallkey.GetValue("InstallDir") as string;
        }

        private static bool CopyTemplate(string PROJECT_TEMPLATE_NAME, DirectoryInfo mossFinnatics)
        {
            string thisDirectoryPath = Directory.GetCurrentDirectory();
            DirectoryInfo thisDirectory = new DirectoryInfo(thisDirectoryPath);
            FileInfo[] zipFiles = thisDirectory.GetFiles("*.zip");
            FileInfo projectTemplate = null;

            projectTemplate = zipFiles.FirstOrDefault(fileinfo => fileinfo.Name == PROJECT_TEMPLATE_NAME);
            if (projectTemplate == null)
            {
                throw new ArgumentNullException("projectTemplate","Project template .zip file not found!");
            }

            if (projectTemplate.CopyTo(mossFinnatics.FullName + @"\" + PROJECT_TEMPLATE_NAME, true) == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private static bool InstallTemplatesWithVisualStudio(DirectoryInfo IDE)
        {
            string devEnvFilePath = IDE.FullName + "devenv.exe";

            try
            {
                using (System.Diagnostics.Process myProc = System.Diagnostics.Process.Start(devEnvFilePath, @"/installvstemplates"))
                {
                    // wait for the templates to be loaded
                    myProc.WaitForExit();

                    // close the cmd window
                    myProc.Close();
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
}
